﻿using System;

namespace iRealtor.Maps.Core.Helpers
{
	public class DistanceHelper
	{
		private const double PIx = 3.141592653589793;
		private const double Radio = 6378.16;
		private const double Offset = 268435456;
		private const double Radius = 85445659.4471; // $offset / PIx()

		public double HaversineDistance(double lat1, double lon1, double lat2, double lon2)
		{
			double dlon = Radians(lon2 - lon1);
			double dlat = Radians(lat2 - lat1);

			double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
			double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));

			return (angle * Radio);
		}

		public static int PixelDistance(double lat1, double lon1, double lat2, double lon2, int zoom)
		{
			var x1 = LonToX(lon1);
			var y1 = LatToY(lat1);

			var x2 = LonToX(lon2);
			var y2 = LatToY(lat2);

			return (int)Math.Sqrt(Math.Pow((x1 - x2), 2) + Math.Pow((y1 - y2), 2)) >> (21 - zoom);
		}

		#region Helpers

		private static double Radians(double x)
		{
			return x * PIx / 180;
		}

		private static double LonToX(double lon)
		{
			return Math.Round(Offset + Radius * lon * PIx / 180);
		}

		private static double LatToY(double lat)
		{
			return Math.Round(Offset - Radius * Math.Log((1 + Math.Sin(lat * PIx / 180)) / (1 - Math.Sin(lat * PIx / 180))) / 2);
		}

		#endregion
	}
}
